Give this a try. It remaps `@` so that `g@` (plus a dummy motion `l`) is used afterwards, thus becoming the last operator and subject to repeating with `.`.

    fun! AtAt(_)
        let s:atcount = v:count ? v:count : s:atcount
        call feedkeys(s:atcount.'@@')
    endfun

    fun! AtNext(_)
        set opfunc=AtAt
    endfun

    " Avoid that a macro could set 'opfunc'.
    fun! AtInit()
        set opfunc=AtNext
        return 'g@l'
    endfun

    nno <expr> <plug>@init AtInit()
    ino <expr> <plug>@init "\<c-o>".AtInit()

    fun! AtReg()
        let c = nr2char(getchar())
        let s:atcount = v:count1
        return '@'.c."\<plug>@init"
    endfun

    nmap <expr> @ AtReg()

I've tried to handle as many corner cases as I can think of. You can
repeat `@:` with `.`. Counts to `@` or `.` are retained for subsequent
presses of `.`.

This is tricky, and I'm not convinced that something won't break
somewhere along the way. So no guarantees, warranties, or promises with
this one.

Personally, I'm okay having a difference between the fine-grained
repeats of `.` for the last change, and the macro repeats of `@@`.