Please post a link to the examples you found that show that.
Although it's not documented in the library reference, you can set the APN via NB::begin():
/** Start the NB IoT modem, attaching to the NB IoT or LTE Cat M1 network
@param pin SIM PIN number (4 digits in a string, example: "1234"). If
NULL the SIM has no configured PIN.
@param apn (optional) APN to use
@param restart Restart the modem. Default is TRUE. The modem receives
a signal through the Ctrl/D7 pin. If it is shut down, it will
start-up. If it is running, it will restart. Takes up to 10
seconds
@param synchronous If TRUE the call only returns after the Start is complete
or fails. If FALSE the call will return inmediately. You have
to call repeatedly ready() until you get a result. Default is TRUE.
@return If synchronous, NB_NetworkStatus_t. If asynchronous, returns 0.
*/
NB_NetworkStatus_t begin(const char* pin = 0, bool restart = true, bool synchronous = true);
NB_NetworkStatus_t begin(const char* pin, const char* apn, bool restart = true, bool synchronous = true);
NB_NetworkStatus_t begin(const char* pin, const char* apn, const char* username, const char* password, bool restart = true, bool synchronous = true);
That's no good. The interesting thing is that the erroneous code line doesn't occur in the "complete sketch" part of the tutorial, only the part of the tutorial that gives the code snippet. If you like, you can report this documentation error via this form:
I'm sure the future MKR NB 1500 users would be very grateful to not have to go through the same confusion you did.