This code works fine in some projects, whereas in others Revit throws an InvalidOperationException saying that there is no tag available in the call to the NewTag method.
The behaviour seems to vary between different projects and on different elements.

How can that be?

Answer: Have you tried either regenerating the document or placing the tag symbol loading and the tag creation calls in separate transaction, committed individually?

Response: Problem solved.
As it turns out, the Revit project needs to have some suitable tag type loaded before calling NewTag.
Your transaction hint was very helpful.
My earlier code was not enough as it stands.
It actually requires separate transactions to load the tag type and add a new tag if there was no other tag loaded before.
I did not previously know what Revit meant by 'there is no tag available'.

Furthermore, I was initially using automatic transaction mode for this command, thinking that would free me from worrying about any transaction handling myself at all.
I now learned that the automatic transaction mode does not enclose each action in a separate transaction, but wraps all executed functions in the whole external command into one single one.
In this case, such an approach is not usable at all.

Many thanks to Max for raising this issue and verifying that the solution works!

Extra Regeneration Required to Populate Materials

One of the issues we took a look at during the DevLab at AU last Tuesday was the list of materials attached to a newly duplicated symbol.

At first glance, it appeared that a duplicated family symbol had zero entries in its list of materials, whereas the original symbols material list was correctly populated.

On further exploration, we discovered that this is another case of retrieving stale data after a model modification.

The behaviour is easily rectified by a call to regenerate the model after the symbol duplication.

Here is the final implementation of the external command implementing to test the issue.
It expects a structural steel column to be pre-selected, which is a family instance whose associated symbol has exactly one entry in its materials list.
We duplicate the symbol.
This requires defining a new name.
To simplify repeated testing, we generate a new name by simply appending the clock tick counter to the original one.
Directly after the call to Duplicate, the new symbol's material list has zero entries, which makes no sense for this kind of symbol.
A call to Regenerate fixes that: