def _compute_metric_names(self):
    """Computes the list of metric names from all the scalar (run, tag) pairs.

    The return value is a list of (tag, group) pairs representing the metric
    names. The list is sorted in Python tuple-order (lexicographical).

    For example, if the scalar (run, tag) pairs are:
    ("exp/session1", "loss")
    ("exp/session2", "loss")
    ("exp/session2/eval", "loss")
    ("exp/session2/validation", "accuracy")
    ("exp/no-session", "loss_2"),
    and the runs corresponding to sessions are "exp/session1", "exp/session2",
    this method will return [("loss", ""), ("loss", "/eval"), ("accuracy",
    "/validation")]

    More precisely, each scalar (run, tag) pair is converted to a (tag, group)
    metric name, where group is the suffix of run formed by removing the
    longest prefix which is a session run. If no session run is a prefix of
    'run', the pair is skipped.

    Returns:
      A python list containing pairs. Each pair is a (tag, group) pair
      representing a metric name used in some session.
    """
    session_runs = self._build_session_runs_set()
    metric_names_set = set()
    run_to_tag_to_content = self.multiplexer.PluginRunToTagToContent(
        scalar_metadata.PLUGIN_NAME)
    for (run, tag_to_content) in six.iteritems(run_to_tag_to_content):
      session = _find_longest_parent_path(session_runs, run)
      if not session:
        continue
      group = os.path.relpath(run, session)
      # relpath() returns "." for the 'session' directory, we use an empty
      # string.
      if group == ".":
        group = ""
      metric_names_set.update((tag, group) for tag in tag_to_content.keys())
    metric_names_list = list(metric_names_set)
    # Sort metrics for determinism.
    metric_names_list.sort()
    return metric_names_list