Using MapAt to map at a particular depth (levelspec)

A combination of Map and MapAt perhaps?

Map[MapAt[f, #, 1] &, A, {2}]

(* ===>  {{{f["15"], "CG"}, {f["391"], "CG"}, {f["412"], "CC3"}}, 
         {{f["3"], "CG"}, {f["16"], "CG"}, {f["392"], "CG"}}} 
*)

To map f to number strings appearing at any position or depth:

Map[If[StringMatchQ[#, NumberString], f[#], #] &, A, {-1}]
(* => {{{f["15"], "CG"}, {f["391"], "CG"}, {f["412"], "CC3"}}, {{f["3"], "CG"}, {f["16"], "CG"}, {f["392"], "CG"}}} *)

another example:

b = {{{"15", "CG"}, {{"391", "CG"}, "230"}, {"412", "CC3"}}, {{"3", 
 "CG"}, {"392", {"CG", {"CG", "345"}}}}};
Map[If[StringMatchQ[#, NumberString], f[#], #] &, b, {-1}]
(* => {{{f["15"], "CG"}, {{f["391"], "CG"}, f["230"]}, {f["412"], "CC3"}}, {{f["3"], "CG"}, {f["392"], {"CG", {"CG", f["345"]}}}}} *)

More options:

Apply[{f[#1], ##2} &, A, {2}]

{f[#1], ##2} & @@@ # & /@ A

ReplacePart[A, {i_, j_, 1} :> f @ A[[i, j, 1]] ]

ReplacePart[A, p:{_, _, 1} :> f @ Extract[A, p] ]