Doh - you're right, I can just pass both the name and the value as arguments of the macro.  I really like this approach - in the future, I can add new modes to the FOR_EACH_TDI_MODE macro and nothing in about_flags.cc will need to change.  Thanks!
CONTENT_EXPORT extern const char kTopDocumentIsolationModeParam[];
#define FOR_EACH_TDI_MODE(V)                                                  \
  V(Xsite, 1, "isolate all frames from sites other than the top-level frame") \
  V(Ads, 2, "isolate ads detected by heuristics")
enum class TopDocumentIsolationMode {
  Default = 0,
#define DEFINE_TDI_MODE_ENUM_VALUE(name, value, description) name = value,
  FOR_EACH_TDI_MODE(DEFINE_TDI_MODE_ENUM_VALUE)
#undef DEFINE_TDI_MODE_ENUM_VALUE
};
#define DEFINE_TDI_MODE_FEATURE_PARAM(name, value, description)               \
  const FeatureEntry::FeatureParam kTopDocumentIsolationVariations_##name[] = \
      {{features::kTopDocumentIsolationModeParam, #value}};
FOR_EACH_TDI_MODE(DEFINE_TDI_MODE_FEATURE_PARAM)
#undef DEFINE_TDI_MODE_FEATURE_PARAM
const FeatureEntry::FeatureVariation kTopDocumentIsolationVariations[] = {
#define DEFINE_TDI_MODE_VARIATION(name, value, description)                 \
  {"(" #name " - " description ")", kTopDocumentIsolationVariations_##name, \
   arraysize(kTopDocumentIsolationVariations_##name), nullptr},
    FOR_EACH_TDI_MODE(DEFINE_TDI_MODE_VARIATION)
#undef DEFINE_TDI_MODE_VARIATION
};