<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _info_from_string(info_string):
 """Parse a `TensorBoardInfo` object from its string representation. Args: info_string: A string representation of a `TensorBoardInfo`, as produced by a previous call to `_info_to_string`. Returns: A `TensorBoardInfo` value. Raises: ValueError: If the provided string is not valid JSON, or if it does not represent a JSON object with a "version" field whose value is `tensorboard.version.VERSION`, or if it has the wrong set of fields, or if at least one field is of invalid type. """


  try:
    json_value = json.loads(info_string)
  except ValueError:
    raise ValueError("invalid JSON: %r" % (info_string,))
  if not isinstance(json_value, dict):
    raise ValueError("not a JSON object: %r" % (json_value,))
  if json_value.get("version") != version.VERSION:
    raise ValueError("incompatible version: %r" % (json_value,))
  expected_keys = frozenset(_TENSORBOARD_INFO_FIELDS)
  actual_keys = frozenset(json_value)
  if expected_keys != actual_keys:
    raise ValueError(
        "bad keys on TensorBoardInfo (missing: %s; extraneous: %s)"
        % (expected_keys - actual_keys, actual_keys - expected_keys)
    )

  # Validate and deserialize fields.
  for key in _TENSORBOARD_INFO_FIELDS:
    field_type = _TENSORBOARD_INFO_FIELDS[key]
    if not isinstance(json_value[key], field_type.serialized_type):
      raise ValueError(
          "expected %r of type %s, but found: %r" %
          (key, field_type.serialized_type, json_value[key])
      )
    json_value[key] = field_type.deserialize(json_value[key])

  return TensorBoardInfo(**json_value)