Obtains all subdirectories with events files.

  The order of the subdirectories returned is unspecified. The internal logic
  that determines order varies by scenario.

  Args:
    path: The path to a directory under which to find subdirectories.

  Returns:
    A tuple of absolute paths of all subdirectories each with at least 1 events
    file directly within the subdirectory.

  Raises:
    ValueError: If the path passed to the method exists and is not a directory.

def GetLogdirSubdirectories(path):
  """Obtains all subdirectories with events files.

  The order of the subdirectories returned is unspecified. The internal logic
  that determines order varies by scenario.

  Args:
    path: The path to a directory under which to find subdirectories.

  Returns:
    A tuple of absolute paths of all subdirectories each with at least 1 events
    file directly within the subdirectory.

  Raises:
    ValueError: If the path passed to the method exists and is not a directory.
  """
  if not tf.io.gfile.exists(path):
    # No directory to traverse.
    return ()

  if not tf.io.gfile.isdir(path):
    raise ValueError('GetLogdirSubdirectories: path exists and is not a '
                     'directory, %s' % path)

  if IsCloudPath(path):
    # Glob-ing for files can be significantly faster than recursively
    # walking through directories for some file systems.
    logger.info(
        'GetLogdirSubdirectories: Starting to list directories via glob-ing.')
    traversal_method = ListRecursivelyViaGlobbing
  else:
    # For other file systems, the glob-ing based method might be slower because
    # each call to glob could involve performing a recursive walk.
    logger.info(
        'GetLogdirSubdirectories: Starting to list directories via walking.')
    traversal_method = ListRecursivelyViaWalking

  return (
      subdir
      for (subdir, files) in traversal_method(path)
      if any(IsTensorFlowEventsFile(f) for f in files)
  )