Build a CacheKey from a TraceGraph.
Walks graph.ops once, copying the name + first-output meta from
each node. Device is taken from the most recent non-empty output;
it is the caller's responsibility to ensure the trace is
single-device (the MpsBuilder rejects mixed-device traces before
hashing).