Q:

Determine if the edges of a graph are distinguishable

Mathematica 12.1 introduces edge tagged graph (EdgeTaggedGraph), which is supposed to solve the problem of distinguishability of parallel edges.  Unfortunately, the feature is not very well done, and there is no way to guarantee distinguishability.  It is allowed that some edges do not have tags at all, or that parallel edges have the very same tag. 
Thus, if we were to implement a function which requires that edges be distinguishable, we must check that that is really the case.  Since this check will be run every time our function is called, it should be very fast.  In Mathematica 12.0 and earlier, which had no edge tagged graphs, one could simply use MultigraphQ. This is an O(1) operation, I assume achieved through caching. 
How can I check that all edges of a graph are distinguishable in Mathematica 12.1, with the best possible performance? 
My current solution:
nonDistinguishableEdgesQ = MultigraphQ[#] && (Not@EdgeTaggedGraphQ[#] || canonicalEdgeBlock@Not@DuplicateFreeQ@EdgeList[#])&

where canonicalEdgeBlock is from here (a still open question also asking for performance improvements).  
I am afraid that unless someone finds an internal function that does this, we are stuck with an O(n) solution.  This question is for finding the fastest such solution. 
Requirements:

As fast as possible. 
Must work on all kinds of graphs that Mathematica supports, including mixed graphs. 
It is acceptable (in fact it is practically necessary) for the function to have multiple branches, selecting the fastest possible method for the type of given input graph. 
It is acceptable to use IGraph/M specific functions, such as IGIndexEdgeList, for the implementation. 

This is the current version (I am still experimenting with speeding it up): https://github.com/szhorvat/IGraphM/blob/master/IGraphM/PropertyTransformations.m#L15

Benchmark
Since this is a performance-tuning question, it is appropriate to add a benchmark, so that people can test their attempts.  The most important case if tagged graphs where edges are distinguishable.  These should be handled as fast as possible. 
SeedRandom[99]
g1 = Graph[Range[1000], RandomInteger[{1, 1000}, {50000, 2}]];
tg1 = EdgeTaggedGraph[g1];

g2 = Graph[Range[200], RandomInteger[{1, 200}, {300, 2}]];
tg2 = EdgeTaggedGraph[g2];

The following implementation relies on internal IGraph/M functions, therefore you need to install IGraph/M before it can be used. 
nonDistinguishableEdgesQ = MultigraphQ[#] && Not[EdgeTaggedGraphQ[#] && distinguishableTaggedEdgesQ[#]]&;
distinguishableTaggedEdgesQ[graph_] :=
    If[MixedGraphQ[graph],
        IGraphM`PackageScope`canonicalEdgeBlock@DuplicateFreeQ@EdgeList[graph]
        ,
        If[UndirectedGraphQ[graph],
        DuplicateFreeQ@Transpose@Append[
            Transpose[IGraphM`PackageScope`igraphGlobal@"edgeListSortPairs"[IGIndexEdgeList[graph]]],
            EdgeTags[graph]
        ],
        DuplicateFreeQ@Transpose@Append[
            Transpose[IGIndexEdgeList[graph]],
            EdgeTags[graph]
        ]
        ]
    ]

Benchmark results:
RepeatedTiming[nonDistinguishableEdgesQ[tg1], 5]
(* {0.0095, False} *)

RepeatedTiming[nonDistinguishableEdgesQ[tg2], 5]
(* {0.000069, False} *)

A:

We can cache the results to speed up subsequent evaluations.  There are several ways to do that (including the "LeastRecentlyUsedCache" DataStructure in M12.1), but one issue is that normal caches will hold a reference to the graph whose result was cached.  Even if the original graph is Cleared, the cache will hold on to it, preventing memory from being freed.  This is a problem if the graph was large. 
To get around this, we can use an ExpressionStore, which conveniently allows associating the result directly with the graph.  If the graph is removed, so is the cache entry. 
After defining:
$exprStore = Language`NewExpressionStore["MyGraphPropCache"]

cachedFun[fun_][arg_] :=
    If[$exprStore@"containsQ"[arg, fun],
  $exprStore@"get"[arg, fun],
      With[{res = fun[arg]},
        $exprStore@"put"[arg, fun, res]; res
      ]
    ]

we can use cachedFun[distinguishableTaggedEdgesQ][graph] instead of distinguishableTaggedEdgesQ[graph].