Robot Name - Exercise
We can create 676000 robots with unique names, because we have 26 possibilities for each 'letter position' and 10 possibilities for 'number position' in our name. So calculation is 26 * 26 * 10 * 10 * 10 = 676000.

Why am I mentioning that? Because that number is not so big and maybe it's worth to consider pregenerating all possible values, keep them in pool and get/return when necessary. That's another approach. I don't want to say that it's better. It will be more memory consuming solution, but robot 'initialization' will be faster. Also it'll be easier to apply fix for point 6. Anyway, you should always get what suits your requirements. 

End of digression - back to your code!


Why I can't see namespaces both in tests and in class? You copied it that way?
I understand why you set up Random as static, but it's not thread safe the way you implemented it. Reference: [JON SKEET ARTICLE]
Static readonly HashSet is very dangerous, because it's instance is shared between all threads and Hashset.Remove method could cause strange problems/exceptions in multithreaded environment. Of course no one is saying that in requirements, but I think that case should never be ignored. ConcurrentDictionary should be your choice in here, because it ensures thread safety. [MSDN]
Letters in alphabet will never change, so you can keep it as a const field. Thanks to that you'll avoid allocation string for each time somebody tries to generate random letters.
In case for readability I have nothing to add it's pretty clear what's happening here.
Last, but most important, comment from my side. A little challenge for you :) what will happen with your code when you create 676000 robots and try to create one more? Hint: you can use code from Robot_names_are_unique() test method, but increase upper limit of iterations to 676000.


Hope this helps!