Should all components/classes/pages etc. have unique name across all the packages of the same namespace?
That depends. Do you expect to have users install two or more packages with conflicting names? If not, you can safely use whatever names you want. Otherwise, if you are designing apps that can connect with each other (e.g. addons and the like), you must make sure all names are unique, or your subscribers will get errors like:
1) Cannot add component of type:ApexClass named:q350426 subjectId:01p8A00000BP3vN to another
package because it is an installed component.,
Details: package.xml: Cannot add component of type:ApexClass named:q350426
subjectId:01p8A00000BP3vN to another package because it is an installed component.
Are there any best practices of how to name packaged components to avoid such naming collision? E.g. should we make up some custom prefix (unique per each package) and prepend it to all components inside that package (sort of imitating custom namespace)?
Not particularly any specific standard that I've heard of. Aside from some common names like "Util" or "TestDataFactory", I would imagine that unrelated projects will probably naturally surface unrelated names.
Ideally, if you need shared metadata, create a shared package as a dependency, and put the shared components there. Otherwise, you may indeed need to prefix or suffix your metadata. What that looks like depends on your own design standards, which generally should be dictated by you, and not us (or Salesforce) to the largest extent possible.
At which stage this components names uniqueness is enforced - package version upload or at package installation time?
During installation time. The reason why is that each package may be viable separately, so there's no requirement to make everything globally unique within your namespace.
Where can we find the full list of package components which should have a unique name?
Everything that has a name must be unique, which is everything you can put into a managed package. As you'll see in the documentation, the Metadata type:
This is the base class for all metadata types. You cannot edit this object. A component is an instance of a metadata type.
This means that absolutely everything, including Custom Labels, Field Sets, Apex Classes, Apex Triggers, Flows, Page Layouts, Permission Sets, must all have unique names within their domain. In other words, you can't have 2 Custom Labels named Demo, but you can have a Custom Label named Demo and an Apex Class named Demo.
Where can we find the full list of package components which should have a unique name?
Everything on this list (which I'm answering only for completeness; it's everything you can possibly package).
tl;dr If you want to install more than one package from the same namespace, they'd better all have unique names for every single component, no matter how trivial. How you manage this is up to you. Prefix, Suffix, or even just using deployment scripts to automatically fail if duplicated names are found.