To fix the syntax of your second attempt:
SELECT @MyTag1 = CASE WHEN TagName= 'MyTag1' THEN TagID ELSE @MyTag1 END
, @MyTag2 = CASE WHEN TagName= 'MyTag2' THEN TagID ELSE @MyTag2 END
WHERE TagName IN ('MyTag1', 'MyTag2')
(I'm not sure what @myValue was doing in there as it wasn't mentioned in the first example, so I've left that out.)
You may find this inefficient (it might scan, or at least do a partial scan) due to
WHERE ... IN ... so watch the query plan. If that is the case then the sub-query option would be more efficient as you'll get two seeks instead.
When using the sub-query method if there might be many rows matching, add in
TOP 1 so that the query engine will stop on finding the first value:
SELECT @myTag1 = (
SELECT TOP 1
WHERE TagName = 'MyTag1'
, @myTag2 = (
SELECT TOP 1
WHERE TagName = 'MyTag2'
(it feels logical to assume that the query planner will be clever enough to know this is what you want, but I have seen it not do so in more complex examples and the explicit
TOP 1 encourage a more efficient plan)
If you need many more properties pulling out than just the one or two, then you might find a
PIVOT based solution more efficient (see Scott's answer for more detail on that). Again, check the resulting query plans for confirmation (and make sure you test with realistic data sizes/patterns or you may get a different plan and therefore performance profile in Dev/Test than in Production).
A question though: is there a reason why you need this to happen in a single statement? The sub-query version should be exactly equivalent to the two statement version and some may find the time simple statements slightly clearer to read. If you are concerned about data changing between the two statements, then wrap them in an explicit transaction (or the larger process if they are part of one) to try enforce consistency.