Perhaps it's best to say that for the time being, they should regard
polymorphic expressions like [] as either one symbol denoting different
values of different types or one value having many types, whichever they
feel more comfortable with.

I would like to be able to say that [ ] is one symbol denoting different values of different types and that the compiler picks which value it denotes given the context. But the example program disallows that--which is how I came up with the example in the first place.

let
   xs = []
   ys = 1:xs
   zs = 'a': xs
in ...

xs is not bound to a value with a concrete type (like [Int] or [Char]) at compile time. Even after compilation xs :: [a].

To say that [ ] is a value having many different types seems to be saying more or less the same thing, namely that compilation doesn't pick a particular concrete type.

So what are the other options? I still like the idea of saying that [ ] is a function that takes a type as an argument and generates a value. (I believe this was your explanation at one point.) I realize that it isn't a function at the Haskell level. But it makes intuitive sense to say that the compiler generates such a function, which is what is bound to xs. It is that function that gets executed when the program is run. I know that for optimization purposes it may be compiled down past that interpretation and I also know that this function isn't a Haskell function.  But if one were giving an operational semantics for what's going on (which I guess is what the Core effectively is) that seems to be the most transparent explanation.