The first part of your question is: "Is there a situation in which naming the self parameter something other than self is useful?" I don't know of any really compelling cases, but even if someone comes up with the perfect example, they're rare enough that I wouldn't look to them as the reason for this design choice: Normal use is far more important than very occasionally having to use self in an unintuitive way. (Note that enforcing the name self would not prevent anyone from getting anything done; it's just a name.)
So why does python allow this? There are two issues here: Why require self to be explicitly listed among the arguments (which gives us the opportunity to choose another name), and why not make self into a keyword, like this in certain other languages.
Why it's not a keyword is pretty clear: The designers of python always try to minimize the number of reserved words in the language (to the point of making every effort to reuse already reserved words when new syntax is introduced, e.g. with yield from, from ... import, and while ... else). So if something could reasonably be implemented without being a reserved word, it is.
Once it was decided that self is not a keyword, but a special identifier, how do you make it special? Making it suddenly appear in the locals() dictionary of every class method would introduce "magic" behavior that is again undesirable: "Explicit is better than implicit." So, self is introduced by declaring in the method signature, and the only special behavior is that this first argument is bound to the object whose method we call. This made it easy to support static and class methods through decorators, without adding special syntax to language. (As this post by Guido explains, "it's trivial to write a decorator that implements @classmethod or @staticmethod in pure Python.") So once the language was designed this way, there's really no going back.