Why not test and see?
regress=> SET enable_seqscan = off;
SET
regress=> explain select * from things where 'blue' = ANY (tags);
QUERY PLAN
---------------------------------------------------------------------------
Seq Scan on things (cost=10000000000.00..10000000037.67 rows=6 width=36)
Filter: ('blue'::text = ANY ((tags)::text[]))
(2 rows)
regress=> explain select * from things where tags <@ '{"blue"}';
QUERY PLAN
------------------------------------------------------------------------------------
Bitmap Heap Scan on things (cost=12.05..21.52 rows=6 width=36)
Recheck Cond: (tags <@ '{blue}'::character varying[])
-> Bitmap Index Scan on index_things_on_tags (cost=0.00..12.05 rows=6 width=0)
Index Cond: (tags <@ '{blue}'::character varying[])
(4 rows)
regress=> explain select * from things where '{"blue","yellow"}' && tags;
QUERY PLAN
-------------------------------------------------------------------------------------
Bitmap Heap Scan on things (cost=12.10..22.78 rows=12 width=36)
Recheck Cond: ('{blue,yellow}'::character varying[] && tags)
-> Bitmap Index Scan on index_things_on_tags (cost=0.00..12.09 rows=12 width=0)
Index Cond: ('{blue,yellow}'::character varying[] && tags)
(4 rows)
So Pg is using the index for the && and <@ queries, but not for = ANY (...).
I'm sure it'd be possible to teach Pg to transform x = ANY (y) into ARRAY[x] @> y, but it doesn't at the moment.
What 2 does is exactly what you say you want. Test if "blue" is one of the tags. It's not an equality test, it's a membership test.
However, if instead of checking a literal value like 'blue' you use a value from another table, I noticed that:
somethings.tag = ANY (otherthings.tags) was faster if the number of otherthings rows was small (it does a sequantial scan on otherthings and uses the index for somethings)
ARRAY[somethings.tag] <@ otherthings.tags was faster if the number of otherthings is larger because it uses the gin index on otherthings but it seems the ARRAY[] construct forces a sequantial scan on somethings. If however you don't need to construct the array, it should use the gin index on both sides.
explain analyzeand all your questions will be answeredselect * from things where tags @> '{"blue"}