/-- The isomorphism between `n ⊗ X` and `normalize X n` is natural (in both `X` and `n`, but
    naturality in `n` is trivial and was "proved" in `normalizeIsoAux`). This is the real heart
    of our proof of the coherence theorem. -/
def normalizeIso : tensorFunc C ≅ normalize' C :=
  NatIso.ofComponents (normalizeIsoAux C)
    (by -- porting note: the proof has been mostly rewritten
      rintro X Y f
      induction' f using Quotient.recOn with f; swap; rfl
      induction' f with _ X₁ X₂ X₃ _ _ _ _ _ _ _ _ _ _ _ _ h₁ h₂ X₁ X₂ Y₁ Y₂ f g h₁ h₂
      · simp only [mk_id, Functor.map_id, Category.comp_id, Category.id_comp]
      · ext n
        dsimp
        rw [mk_α_hom, NatTrans.comp_app, NatTrans.comp_app]
        dsimp [NatIso.ofComponents, normalizeMapAux, whiskeringRight, whiskerRight, Functor.comp]
        simp only [comp_tensor_id, associator_conjugation, tensor_id,
          Category.comp_id]
        simp only [← Category.assoc]
        congr 4
        simp only [Category.assoc, ← cancel_epi (𝟙 (inclusionObj n.as) ⊗ (α_ X₁ X₂ X₃).inv),
          pentagon_inv_assoc (inclusionObj n.as) X₁ X₂ X₃,
          tensor_inv_hom_id_assoc, tensor_id, Category.id_comp, Iso.inv_hom_id,
          Category.comp_id]
      · ext n
        dsimp
        rw [mk_α_inv, NatTrans.comp_app, NatTrans.comp_app]
        dsimp [NatIso.ofComponents, normalizeMapAux, whiskeringRight, whiskerRight, Functor.comp]
        simp only [Category.assoc, comp_tensor_id, tensor_id, Category.comp_id,
          pentagon_inv_assoc, ← associator_inv_naturality_assoc]
        rfl
      · ext n
        dsimp [Functor.comp]
        rw [mk_l_hom, NatTrans.comp_app, NatTrans.comp_app]
        dsimp [NatIso.ofComponents, normalizeMapAux, whiskeringRight, whiskerRight, Functor.comp]
        simp only [triangle_assoc_comp_right_assoc, Category.assoc, Category.comp_id]
        rfl
      · ext n
        dsimp [Functor.comp]
        rw [mk_l_inv, NatTrans.comp_app, NatTrans.comp_app]
        dsimp [NatIso.ofComponents, normalizeMapAux, whiskeringRight, whiskerRight, Functor.comp]
        simp only [triangle_assoc_comp_left_inv_assoc, inv_hom_id_tensor_assoc, tensor_id,
          Category.id_comp, Category.comp_id]
        rfl
      · ext n
        dsimp
        rw [mk_ρ_hom, NatTrans.comp_app, NatTrans.comp_app]
        dsimp [NatIso.ofComponents, normalizeMapAux, whiskeringRight, whiskerRight, Functor.comp]
        simp only [← (Iso.inv_comp_eq _).2 (rightUnitor_tensor _ _), Category.assoc,
          ← rightUnitor_naturality, Category.comp_id]; rfl
      · ext n
        dsimp
        rw [mk_ρ_inv, NatTrans.comp_app, NatTrans.comp_app]
        dsimp [NatIso.ofComponents, normalizeMapAux, whiskeringRight, whiskerRight, Functor.comp]
        simp only [← (Iso.eq_comp_inv _).1 (rightUnitor_tensor_inv _ _), rightUnitor_conjugation,
          Category.assoc, Iso.hom_inv_id_assoc, Iso.inv_hom_id_assoc, Iso.inv_hom_id,
          Discrete.functor, Category.comp_id, Function.comp]
      · rw [mk_comp, Functor.map_comp, Functor.map_comp, Category.assoc, h₂, reassoc_of% h₁]
      · ext ⟨n⟩
        replace h₁ := NatTrans.congr_app h₁ ⟨n⟩
        replace h₂ := NatTrans.congr_app h₂ ((Discrete.functor (normalizeObj X₁)).obj ⟨n⟩)
        have h₃ := (normalizeIsoAux _ Y₂).hom.naturality ((normalizeMapAux f).app ⟨n⟩)
        have h₄ : ∀ (X₃ Y₃ : N C) (φ : X₃ ⟶ Y₃), (Discrete.functor inclusionObj).map φ ⊗ 𝟙 Y₂ =
            (Discrete.functor fun n ↦ inclusionObj n ⊗ Y₂).map φ := by
          rintro ⟨X₃⟩ ⟨Y₃⟩ φ
          obtain rfl : X₃ = Y₃ := φ.1.1
          simp only [discrete_functor_map_eq_id, tensor_id]
          rfl
        rw [NatTrans.comp_app, NatTrans.comp_app] at h₁ h₂ ⊢
        dsimp [NatIso.ofComponents, normalizeMapAux, whiskeringRight, whiskerRight,
          Functor.comp, Discrete.natTrans] at h₁ h₂ h₃ ⊢
        rw [mk_tensor, associator_inv_naturality_assoc, ← tensor_comp_assoc, h₁,
          Category.assoc, Category.comp_id, ← @Category.id_comp (F C) _ _ _ (@Quotient.mk _ _ g),
          tensor_comp, Category.assoc, Category.assoc, Functor.map_comp]
        

Proof state:
case f.tensor.w.h.mk
C : Type u
X Y X₁ X₂ Y₁ Y₂ : F C
f : X₁ ⟶ᵐ Y₁
g : X₂ ⟶ᵐ Y₂
n : NormalMonoidalObject C
h₁ :
  (𝟙 (inclusionObj n) ⊗ ⟦f⟧) ≫ (normalizeIsoApp C Y₁ { as := n }).hom =
    (normalizeIsoApp C X₁ { as := n }).hom ≫ (Discrete.functor inclusionObj).map ((normalizeMapAux f).app { as := n })
h₂ :
  (𝟙 (inclusionObj ((Discrete.functor (normalizeObj X₁)).obj { as := n }).as) ⊗ ⟦g⟧) ≫
      (normalizeIsoApp C Y₂ ((Discrete.functor (normalizeObj X₁)).obj { as := n })).hom =
    (normalizeIsoApp C X₂ ((Discrete.functor (normalizeObj X₁)).obj { as := n })).hom ≫
      (Discrete.functor inclusionObj).map
        ((normalizeMapAux g).app ((Discrete.functor (normalizeObj X₁)).obj { as := n }))
h₃ :
  (Discrete.functor fun n => inclusionObj n ⊗ Y₂).map ((normalizeMapAux f).app { as := n }) ≫
      (normalizeIsoApp C Y₂ ((Discrete.functor (normalizeObj Y₁)).obj { as := n })).hom =
    (normalizeIsoApp C Y₂ ((Discrete.functor (normalizeObj X₁)).obj { as := n })).hom ≫
      (Discrete.functor inclusionObj).map
        ((Discrete.functor (normalizeObj Y₂)).map ((normalizeMapAux f).app { as := n }))
h₄ :
  ∀ (X₃ Y₃ : (Discrete ∘ NormalMonoidalObject) C) (φ : X₃ ⟶ Y₃),
    (Discrete.functor inclusionObj).map φ ⊗ 𝟙 Y₂ = (Discrete.functor fun n => inclusionObj n ⊗ Y₂).map φ
⊢ (α_ (inclusionObj n) X₁ X₂).inv ≫
      ((normalizeIsoApp C X₁ { as := n }).hom ⊗ 𝟙 X₂) ≫
        ((Discrete.functor inclusionObj).map ((normalizeMapAux f).app { as := n }) ⊗ ⟦g⟧) ≫
          (normalizeIsoApp C Y₂ (normalizeObj Y₁ n)).hom =
    (α_ (inclusionObj n) X₁ X₂).inv ≫
      ((normalizeIsoApp C X₁ { as := n }).hom ⊗ 𝟙 X₂) ≫
        (normalizeIsoApp C X₂ (normalizeObj X₁ n)).hom ≫
          (Discrete.functor inclusionObj).map ((normalizeMapAux g).app (normalizeObj X₁ n)) ≫
            (Discrete.functor inclusionObj).map
              ((Discrete.functor (normalizeObj Y₂)).map ((normalizeMapAux f).app { as := n }))

Next tactic:
congr 2