One potentially significant advantage of not using the same private key for both the lobby and the game servers is that, even if one or more of the game server keys is compromised, the lobby server key (whose public half is bundled with the client, making it hard to change) is still safe.
Presumably, the game servers present a significantly larger (and more frequently changing) attack surface than a dedicated lobby server, so it makes sense to design your system to be able to recover from an attack on the game servers, while making the lobby server as hard to compromise as possible.
Your third alternative also shares this advantage, since only the login server needs to know the private half of the bundled key. Indeed, depending what else besides authentication the "lobby" server is doing, separating the critical authentication functions onto a dedicated server may be a good idea.
Also, your third alternative guarantees that clients will not be able to bypass the lobby/login server even if they somehow manage to acquire a copy of the game server public keys (e.g. from another, compromised, client). (The client could still bypass the login server if they somehow acquired another client's symmetric key, but since those keys are tied to client IDs, your servers should be able to detect it.) Depending on your use case, this may or may not be an advantage, but at least it shouldn't hurt.
BTW, I feel like I really should amend this old answer to note that there's a more secure (and practical) option than any of those described above:
Don't bundle any of the game or lobby server public keys in the client. Instead, bundle the public half of a "root" digital signature key, while keeping the private half somewhere safe (i.e. not on any publicly accessible servers).
Use the private root key to sign the public keys of your game and lobby servers.
When a client connects to a server, the server first presents (over an insecure channel) a "certificate" containing its signed public key. The client first verifies the signature using its bundled public root key, and then establishes a secure channel to the server using the verified public key.
You will also need some mechanism of revoking compromised server keys. The simplest way is to attach an expiration timestamp to the public server key before signing it, and have the client refuse to use an expired key. Of course, this means that you'll have to change (or at least re-sign) the server keys at regular intervals before they expire, which is something you'll want to automate.
You can also include in your protocol an option for e.g. the auth/lobby server to send the client a list of revoked server keys that the client should not trust even if they otherwise look valid. This will at least allow quick revocation of game server keys, without having to wait for them to expire. This can be useful e.g. if some game servers are run by third parties who cannot easily receive automated key updates, making it inconvenient to use a very short expiration time for their keys.
Of course, another option could be to give such third-party game server operators their own "branch" signing key, itself signed by the root key, so that they can generate and sign their own server keys. Of course, the client then needs to be able to follow such chains of signed keys all the way up to the bundled root key. And the branch keys need to carry some (signed) metadata indicating which servers they're valid for, so that the third party can't e.g. just generate and sign their own lobby/auth server keys.
The nice thing, though, is that you don't really have to implement any of those features yourself, since they're all part of the public key infrastructure model used in TLS (and DTLS), which is the protocol that e.g. your web browser uses to connect securely to Stack Exchange (and to any other HTTPS website). While TLS is a very complex protocol (party due to historical accumulation of features) that you really don't want to implement yourself, there are plenty of TLS libraries that you can use. Nowadays, it's more than likely that your language runtime even has one bundled in. (If it can fetch data from an
https:// URL, it does, or uses one bundled with your OS.)
Of course, you'll still need to learn how to configure your TLS library to suit your needs (e.g. to only trust your own root certificate and to disable any legacy features you don't want) and how to generate and sign TLS keys, which can be a non-trivial task in itself. But it's certainly a lot easier than implementing a secure communications protocol all by yourself from scratch.